#include "parafluidsegment.h"

#include <cmath>

using namespace ParaFluid;

Segment::~Segment()
{
	/* does nothing*/
}

Segment::Segment()
	: pointA()
	, pointB()
{
	/* does nothing */
}

Segment::Segment(const Vector & PointA, const Vector & PointB)
	: pointA(PointA)
	, pointB(PointB)
{
	/* does nothing */
}

Segment::Segment(const Atom & atom)
	: pointA(atom.previousPosition)
	, pointB(atom.currentPosition)
{
	/* does nothing */
}

Segment::Segment(const Segment & other)
	: pointA(other.pointA)
	, pointB(other.pointB)
{
	/* does nothing */
}

Segment & Segment::operator= (const Segment & rhs)
{
	if(&rhs != this)
	{
		pointA = rhs.pointA;
		pointB = rhs.pointB;
	}
	return *this;
}

inline float sgn(float value)
{
	if(value < 0)
	{
		return -1;
	}
	else if(value > 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

QList<Vector> Segment::visitedVoxels(float smoothingDistance)
{
	QList<Vector> result;
	
	float x = pointA.x;
	float y = pointA.y;
	float z = pointA.z;
	
	float dx = pointB.x - pointA.x;
	float dy = pointB.y - pointA.y;
	float dz = pointB.z - pointA.z;
	
	float sx = sgn(dx) * smoothingDistance;
	float sy = sgn(dy) * smoothingDistance;
	float sz = sgn(dz) * smoothingDistance;
	
	float ax = fabs(dx);
	float ay = fabs(dy);
	float az = fabs(dz);
	
	float bx = 2 * ax;
	float by = 2 * ay;
	float bz = 2 * az;
	
	float exy = ay - ax;
	float exz = az - ax;
	float ezy = ay - az;
	
	int n = 3;
	n += ax / smoothingDistance;
	n += ay / smoothingDistance;
	n += az / smoothingDistance;
	
	while(n--)
	{
		result.append(Vector(x, y, z));
		
		if(exy < 0)
		{
			if(exz < 0)
			{
				x += sx;
				exy += by;
				exz += bz;
			}
			else
			{
				z += sz;
				exz -= bx;
				ezy += by;
			}
		}
		else
		{
			if(ezy < 0)
			{
				z += sz;
				exz -= bx;
				ezy += by;
			}
			else
			{
				y += sy;
				exy -= bx;
				ezy -= bz;
			}
		}
	}
	
	return result;
}

